<?php
if (!defined('ENGINE_NAME')) die ("You can't access this file directly!");

class MasterPlugin
{
	function Init() { return -1; }
	function HandlePage() { return -1; }
	function HandleAction() { return -1; }
	function HandleFilter() { return -1; }
}

class CPlugin { }

class CPlugins {

	var $aConfig		= false;
	var $aPages			= false;
	var $aActs			= false;
	var $aFilters		= false;
	var $aList			= false;
	var $aListActive	= false;

	/**
	* Load language file for plugin
	* @author Bogdan Tkachenko (http://bogus.mail.ua)
	* @param sPlugin Plugin ID
	* @return true if plugin language loaded and false if not
	*/
	function LoadLang($sPlugin = 'core')
	{
		global $g_aLang, $g_sLanguage, $oXml;

		if (isset($g_aLang[$sPlugin]))
		{
			return false;
		}

		if ($sPlugin == 'core') {
			$sWhere = ENGINE_DIR."languages/$g_sLanguage.xml";
		}
		else
		{
			$sWhere = ENGINE_DIR."plugins/$sPlugin/languages/$g_sLanguage.xml";
		}

		if (!file_exists($sWhere))
		{
			return false;	
		}

		$sContent = file_get_contents($sWhere);
		$hParser = xml_parser_create('');
		xml_parser_set_option($hParser, XML_OPTION_TARGET_ENCODING, "UTF-8");
		xml_parser_set_option($hParser, XML_OPTION_CASE_FOLDING, 0);
		xml_parser_set_option($hParser, XML_OPTION_SKIP_WHITE, 1);
		xml_parse_into_struct($hParser, trim($sContent), $aXml);
		xml_parser_free($hParser);

		if ($aXml)
		{
			$aNewLang = array();
			$aGroups = array();

			foreach ($aXml as $aItem)
			{
				if ($aItem['tag']=='string' && $aItem['type']=='complete')
				{
					if (isset($aItem['attributes']['name']) && $aItem['attributes']['name'])
					{
						$aNewGroups = $aGroups;
						$aNewGroups[] = $aItem['attributes']['name'];
						krsort($aNewGroups);
						$aArr = ArrayRecursion($aNewGroups, $aItem['value']);
						$aNewLang = array_merge_recursive($aNewLang, $aArr);
					}
				}
				else if ($aItem['tag']=='group')
				{
					if ($aItem['type']=='open' && isset($aItem['attributes']['name']) && $aItem['attributes']['name'])
					{
						$aGroups[] = $aItem['attributes']['name'];
					}
					else if($aItem['type']=='close')
					{
						$aTmp = $aGroups;
						$aGroups = array();
						for ($i = 0; $i < count($aTmp)-1; $i++)
						{
							$aGroups[$i] = $aTmp[$i];
						}
					}
				}
			}	
		}

		if (!isset($g_aLang) || !is_array($g_aLang))
		{
			$g_aLang = array();
		}

		$g_aLang[$sPlugin] = $aNewLang;

		return true;
	}

	/**
	* Get config value of variable for specified plugin
	* @author NG CMS Team, Bogdan Tkachenko (http://bogus.mail.ua)
	* @param sPlugin Plugin ID
	* @param sVar Variable
	* @return config value of variable for specified plugin
	*/
	function GetParam($sPlugin, $sVar)
	{
		if (!$sPlugin || !$sVar)
		{
			return false;
		}
		
		if (!is_array($this->aConfig))
		{
			$this->LoadConfig();
		}

		if (!isset($this->aConfig[$sPlugin][$sVar]))
		{
			$this->aConfig[$sPlugin][$sVar] = '';
		}

		return $this->ExecuteFilters('GetParam', $this->aConfig[$sPlugin][$sVar]);
	}

	/**
	* Get config value of variable for specified plugin
	* @author NG CMS Team, Bogdan Tkachenko (http://bogus.mail.ua)
	* @param sPlugin Plugin ID
	* @param sVar Variable
	* @param uValue Variable new value
	* @return true is varible is variable setted and false if it is not
	*/
	function SetParam($sPlugin, $sVar, $uValue)
	{
		if (!$sPlugin || !$sVar) return false;
		if (!is_array($this->aConfig)) { $this->LoadConfig(); }

		$this->aConfig[$sPlugin][$sVar] = $this->ExecuteFilters('SetParam', $uValue);
		return true;
	}

	/**
	* Register plugin page
	* @author Bogdan Tkachenko (http://bogus.mail.ua)
	* @param sPlugin Plugin ID
	* @param sName Page ID
	* @param sRegEx Regular expression to find plugin for this request
	* @param iPrio Page priority. Default 0
	* @return true if page is registered and false if it is not
	*/	function RegisterPage($sPlugin, $sName, $sRegEx, $iPrio=0)
	{
		if (!$sPlugin || !$sName || !$sRegEx)
		{
			return false;
		}
		
		if (isset($this->aPages[$sName]))
		{
			return false;
		}

		$this->aPages[$sName] = array  	(
										'Plugin'	=>	$sPlugin,
										'Name'		=>	$sName,
										'RegEx'		=>	$sRegEx,
										'Prio'		=>	$iPrio										
										);

		return true;
	}

	/**
	* Register event action
	* @author Bogdan Tkachenko (http://bogus.mail.ua)
	* @param sPlugin Plugin ID
	* @param sEvent Event ID	
	* @param sName Action ID
	* @param iPrio Event priority. Default 0
	* @return true if event is registered and false if it is not
	*/
	function RegisterAction($sPlugin, $sEvent, $sName, $iPrio=0)
	{
		if (!$sPlugin || !$sEvent || !$sName)
		{
			return false;
		}

		if (!isset($this->aActs[$sEvent]))
		{
			$this->aActs[$sEvent] = array();
		}

		if (isset($this->aActs[$sEvent][$sName]))
		{
			return false;
		}

		$this->aActs[$sEvent][$sName] = array	(
											'Plugin'	=> $sPlugin,
											'Event'		=> $sEvent,											
											'Name'		=> $sName,
											'Prio'		=> $iPrio
											);

		return true;
	}

	/**
	* Register filter
	* @author Bogdan Tkachenko (http://bogus.mail.ua)
	* @param sPlugin Plugin ID
	* @param sEvent Event ID	
	* @param sName Filter ID
	* @param iPrio Filter priority. Default 0
	* @return true if filter is registered and false if it is not
	*/
	function RegisterFilter($sPlugin, $sEvent, $sName, $iPrio=0)
	{
		if (!$sPlugin || !$sEvent || !$sName)
		{
			return false;
		}

		if (!isset($this->aFilters[$sEvent]))
		{
			$this->aFilters[$sEvent] = array();
		}

		if (isset($this->aFilters[$sEvent][$sName]))
		{
			return false;
		}

		$this->aFilters[$sEvent][$sName] = array	(
													'Plugin'	=> $sPlugin,
													'Event'		=> $sEvent,
													'Name'		=> $sName,
													'Prio'		=> $iPrio
													);
		return true;
	}

	/**
	* Execute event
	* @author Bogdan Tkachenko (http://bogus.mail.ua)
	* @param sEvent Event ID	
	* @param uParams Plugin receives this param
	* @return Plugins events output
	*/
	function ExecuteEvent($sEvent, $uParams=false)
	{
		if (!isset($this->aActs[$sEvent]))
		{
			return true;
		}

		usort($this->aActs[$sEvent], 'SortPlugins');
		
		$aResult = array();
		foreach ($this->aActs[$sEvent] as $sAct)
		{
			$aResult[$sAct['Name']] = $sAct['Plugin']->HandleAction($sAct['Name'], $uParams);
		}

		return $aResult;
	}

	/**
	* Execute filters
	* @author Bogdan Tkachenko (http://bogus.mail.ua)
	* @param sEvent Event ID	
	* @param uVar Variable to filter
	* @return Filtered variable
	*/
	function ExecuteFilters($sEvent, $uVar)
	{
		if (!isset($this->aFilters[$sEvent]))
		{
			return $uVar;
		}

		usort($this->aFilters[$sEvent], 'SortPlugins');

		foreach($this->aFilters[$sEvent] as $aFilter) {
			$uVar = $aFilter['Plugin']->HandleFilter($aFilter['Name'], $uVar);
		}

		return $uVar;
	}

	/**
	* Load plugin page
	* @author Bogdan Tkachenko (http://bogus.mail.ua)
	* @param sRequest Request string
	* @return Page output
	*/
	function LoadPage($sRequest)
	{
		global $g_aLang;
		
		if (preg_match("%^version\/{0,1}$%si", $sRequest))
		{
			return sprintf($g_aLang['core']['version_info'], ENGINE_NAME, ENGINE_VERSION);
		}
		
		if (!is_array($this->aPages))
		{
			return false;
		}
		
		usort($this->aPages, "SortPlugins");

		$sResult = '';
		foreach ($this->aPages as $aPage)
		{
			if (preg_match($aPage['RegEx'], $sRequest, $aScan))
			{
				$sResult = $aPage['Plugin']->HandlePage($aPage['Name'], $aScan);
				break;
			}
		}
		
		return $sResult;
	}

	/**
	* Load plugin info file
	* @author Bogdan Tkachenko (http://bogus.mail.ua)
	* @param sPlugin Plugin ID
	* @return Plugin info
	*/
	function LoadPluginInfo($sPlugin)
	{
		$aFields = array('Version', 'Class', 'Depends');
		$aReqFields = array('Version', 'Class');

		$sFileName = ENGINE_DIR."plugins/$sPlugin/plugin.ini";
		if (!file_exists($sFileName))
		{
			return false;
		}

		$aPlugin = array();
		$aPlugin['Id'] = $sPlugin;
		
		foreach (parse_ini_file($sFileName, false) as $sVar=>$uValue) {
			if (in_array($sVar, $aFields))
			{
				$aPlugin[$sVar] = $uValue;
			}
		}
	
		if (isset($aPlugin['Depends']) && $aPlugin['Depends'])
		{
			$aPlugin['Depends'] = explode(',', str_replace(' ', '', $aPlugin['Depends']));
		}

		foreach ($aReqFields as $sField)
		{
			if (!isset($aPlugin[$sField]) || !$aPlugin[$sField])
			{
				return false;
			}
		}

		return $aPlugin;
	}

	/**
	* Get enabled plugins list
	* @author Bogdan Tkachenko (http://bogus.mail.ua)
	* @return array of plugins list and their info or false
	*/
	function GetList()
	{
		$sFileName = CONF_DIR.'plugins.lst';
		if (!file_exists($sFileName))
		{
			return false;
		}
		
		$aPlugins = array();

		$aPluginsList = file($sFileName);
		foreach ($aPluginsList as $sPlugin)
		{
			$sPlugin = trim($sPlugin);
			if (substr($sPlugin, 0, 1)!='#' &&
				file_exists(ENGINE_DIR."plugins/$sPlugin/plugin.ini") &&
				!isset($aPlugins[$sPlugin]))
			{
				if ($sPluginInfo = $this->LoadPluginInfo($sPlugin))
				{
					$aPlugins[$sPlugin] = $sPluginInfo;
				}
			}
		}

		$this->aList 		= $aPlugins;

		return $aPlugins;
	}

	/**
	* Load plugins config file
	* @author Bogdan Tkachenko (http://bogus.mail.ua)
	* @return true if config is loaded or false if it is not
	*/
	function LoadConfig()
	{
		if (!file_exists(CONF_DIR.'plugins.txt'))
		{
			return false;
		}

		$sConfig = file_get_contents(CONF_DIR.'plugins.txt');
		$this->aConfig = json_decode($sConfig, true);

		return true;
	}

	/**
	* Save plugins config file
	* @author Bogdan Tkachenko (http://bogus.mail.ua)
	* @return true if config is saved or false if it is not
	*/
	function SaveConfig()
	{
		if (!is_array($this->aConfig))
		{
			return false;
		}
		
		if (!is_writable(CONF_DIR.'plugins.ini'))
		{
			return false;
		}
		
		$fFile = fopen(CONF_DIR.'plugins.ini', 'w');
		foreach (array_keys($this->aConfig) as $sPlugin)
		{
				fwrite($fFile, sprintf("[%s]\n", $sPlugin));
				foreach (array_keys($this->aConfig[$sPlugin]) as $sKey)
				{
					fwrite($fFile, sprintf("%s\t\t=%s\n", $sKey, $this->aConfig[$sPlugin][$sKey]));
				}
				fwrite($fFile, "\n");
		}
		fclose($fFile);
		
		return true;
	}
}
